﻿#include "GraphProviderManager.h"

// Graph widget
#include "FITK_Kernel/FITKCore/FITKAbstractGraphWidget.h"
#include "FITK_Component/FITKRenderWindowVTK/FITKGraph3DWindowVTK.h"

// Provider
#include "GraphModelProvider.h"
#include "GraphMarkProvider.h"

namespace GraphData
{
    // 静态变量初始化
    GraphProviderManager* GraphProviderManager::s_instance = nullptr;
    QMutex GraphProviderManager::m_mutex;

    GraphProviderManager* GraphProviderManager::getInstance()
    {
        // 获取单例实例。
        if (!s_instance)
        {
            s_instance = new GraphProviderManager;
        }

        return s_instance;
    }

    void GraphProviderManager::Delete()
    {
        // 手动销毁实例。
        if (s_instance)
        {
            delete s_instance;
        }

        s_instance = nullptr;
    }

    GraphProviderManager::GraphProviderManager()
    {

    }

    GraphProviderManager::~GraphProviderManager()
    {
        // 清除数据管理器。
        deleteProviders(m_modelProviders);
        deleteProviders(m_markProviders);
    }

    GraphModelProvider* GraphProviderManager::getModelProvider(Comp::FITKGraph3DWindowVTK* graphWidget)
    {
        if (!graphWidget)
        {
            return nullptr;
        }

         // 如果没有对应该视口的管理器则创建，有则返回。
        for (GraphModelProvider* provider : m_modelProviders)
        {
            if (!provider)
            {
                continue;
            }

            if (provider->getGraphWidget() == graphWidget)
            {
                return provider;
            }
        }

        // 不存在则创建新管理器。
        GraphModelProvider* newProvider = new GraphModelProvider(graphWidget);
        m_modelProviders.push_back(newProvider);

        // 检测析构信号绑定。
        connect(newProvider, &GraphModelProvider::sig_needToDelete, this, &GraphProviderManager::slot_providerNeedToBeDeleted);

        return newProvider;
    }

    GraphMarkProvider* GraphProviderManager::getMarkProvider(Comp::FITKGraph3DWindowVTK* graphWidget)
    {
        if (!graphWidget)
        {
            return nullptr;
        }

        // 如果没有对应该视口的管理器则创建，有则返回。
        for (GraphMarkProvider* provider : m_markProviders)
        {
            if (!provider)
            {
                continue;
            }

            if (provider->getGraphWidget() == graphWidget)
            {
                return provider;
            }
        }

        // 不存在则创建新管理器。
        GraphMarkProvider* newProvider = new GraphMarkProvider(graphWidget);
        m_markProviders.push_back(newProvider);

        // 检测析构信号绑定。
        connect(newProvider, &GraphMarkProvider::sig_needToDelete, this, &GraphProviderManager::slot_providerNeedToBeDeleted);

        return newProvider;
    }

    void GraphProviderManager::slot_providerNeedToBeDeleted()
    {
        // 判断是否通过信号触发。
        //@{
        QObject* sendPtr = sender();
        if (!sendPtr)
        {
            return;
        }
        //@}

        // 获取算例ID。
        //@{
        GraphProviderBase* pBase = dynamic_cast<GraphProviderBase*>(sendPtr);
        if (!pBase)
        {
            return;
        }
        //@}

        // 类型判断并移出数据管理。
        //@{
        QString className = pBase->getClassName();
        if (className == QString("GraphModelProvider"))
        {
            m_modelProviders.removeOne(dynamic_cast<GraphModelProvider*>(sendPtr));
        }
        else if (className == QString("GraphMarkProvider"))
        {
            m_markProviders.removeOne(dynamic_cast<GraphMarkProvider*>(sendPtr));
        }
        //@}
    }

    void GraphProviderManager::updateObjectById(int dataId, bool forceUpdate)
    {
        if (dataId == -1)
        {
            return;
        }

        bool flag = false;

        // 刷新模型。
        for (GraphModelProvider* provider : m_modelProviders)
        {
            if (!flag)
            {
                flag = provider->updateObjById(dataId, forceUpdate);
            }
        }
        
        // 刷新符号。
        for (GraphMarkProvider* provider : m_markProviders)
        {
            if (!flag)
            {
                flag = provider->updateObjById(dataId, forceUpdate);
            }
        }
    }
}   // namespace GraphData